import cv2
import numpy as np
import matplotlib.pyplot as plt

def sift_feature_detection(image_path):
    """
    使用SIFT进行特征点检测和描述符提取
    
    Args:
        image_path: 图像路径
    
    Returns:
        keypoints: 关键点
        descriptors: 描述符
        gray: 灰度图像
    """
    # 读取图像
    img = cv2.imread(image_path)
    if img is None:
        raise ValueError(f"无法读取图像: {image_path}")
    
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 创建SIFT对象
    sift = cv2.SIFT_create()
    
    # 检测关键点和计算描述符
    keypoints, descriptors = sift.detectAndCompute(gray, None)
    
    return keypoints, descriptors, gray

def compare_images(image1_path, image2_path):
    """
    比较两幅图像的SIFT特征
    
    Args:
        image1_path: 第一幅图像路径
        image2_path: 第二幅图像路径
    """
    # 对两幅图像进行SIFT特征提取
    kp1, des1, gray1 = sift_feature_detection(image1_path)
    kp2, des2, gray2 = sift_feature_detection(image2_path)
    
    # 创建特征匹配器
    bf = cv2.BFMatcher()
    matches = bf.knnMatch(des1, des2, k=2)
    
    # 应用比率测试筛选好的匹配
    good_matches = []
    for m, n in matches:
        if m.distance < 0.75 * n.distance:
            good_matches.append(m)
    
    # 计算匹配质量
    match_quality = len(good_matches) / min(len(kp1), len(kp2))
    
    # 绘制特征点
    img1_kp = cv2.drawKeypoints(gray1, kp1, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
    img2_kp = cv2.drawKeypoints(gray2, kp2, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
    
    # 绘制匹配结果
    matches_img = cv2.drawMatches(gray1, kp1, gray2, kp2, good_matches, None,
                                 flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
    
    # 显示结果
    plt.figure(figsize=(15, 10))
    
    plt.subplot(231)
    plt.imshow(gray1, cmap='gray')
    plt.title('src1')
    
    plt.subplot(232)
    plt.imshow(gray2, cmap='gray')
    plt.title('src2')
    
    plt.subplot(233)
    plt.imshow(matches_img)
    plt.title('matches_img')
    
    plt.subplot(234)
    plt.imshow(img1_kp)
    plt.title('SIFT 1')
    
    plt.subplot(235)
    plt.imshow(img2_kp)
    plt.title('SIFT 2')
    
    plt.subplot(236)
    plt.text(0.5, 0.5, f'match quality: {match_quality:.2%}\n' +
             f'good matches: {len(good_matches)}\n' +
             f'match num: {len(kp1)}/{len(kp2)}',
             horizontalalignment='center',
             verticalalignment='center',
             fontsize=12)
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()

if __name__ == "__main__":
    image1_path = "image1.jpg"
    image2_path = "image3.jpg"
    
    compare_images(image1_path, image2_path)
